package cn.com.youjile.client;

import cn.com.youjile.coding.GeneralDecoder;
import cn.com.youjile.coding.GeneralEncoder;
import cn.com.youjile.handler.GeneralClientHandler;
import cn.com.youjile.listener.ConnListener;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * @Author youjile
 * @CreateDate 2021/3/12
 * @Describe 客户端
 */
public class GeneralClient implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(GeneralClient.class);

    private static boolean is_open_heart = true;    //是否开启心跳功能，true开启，false不开启

    public static Channel serverChannel = null;

    public int port;
    public String host;

    public GeneralClient(String host, int port){
        this.host = host;
        this.port = port;
    }

    @Override
    public void run() {
        ConnListener.resetConnCount();        //重置连接次数
        logger.info("启动客户端,host=[" + this.host + "],port=[" + this.port + "]......");
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        Bootstrap b = new Bootstrap();
        try {
            b.group(workerGroup);
            b.channel(NioSocketChannel.class);
            b.option(ChannelOption.TCP_NODELAY, true);
            b.handler(new LoggingHandler(LogLevel.INFO));
            b.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline pipeline = ch.pipeline();
                    pipeline.addLast("GeneralDecoder", new GeneralDecoder());
                    pipeline.addLast("GeneralEecoder", new GeneralEncoder());
                    if(GeneralClient.is_open_heart) {
                        pipeline.addLast("ping", new IdleStateHandler(75,60,120, TimeUnit.SECONDS));
                    }
                    pipeline.addLast(new GeneralClientHandler());
                }
            });
            //发起异步连接操作，直到成功
            ChannelFuture f = b.connect(host, port);
            f.addListener(new ConnListener());
            Channel channel = f.sync().channel();
            //等待客户端链路关闭
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //优雅退出，释放线程池资源
            //workerGroup.shutdownGracefully(); //由于需要断线重连，所以这里不关闭workerGroup
        }
    }

}
